package cn.matezk.lianlian.controller;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.matezk.lianlian.beans.*;
import cn.matezk.lianlian.model.Device;
import cn.matezk.lianlian.service.IDeviceBindService;
import cn.matezk.lianlian.service.IDeviceService;
import cn.matezk.lianlian.service.ITencentService;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.iotcloud.v20210408.models.DescribeDeviceResponse;
import com.tencentcloudapi.iotexplorer.v20190423.models.CallDeviceActionSyncResponse;
import com.tencentcloudapi.iotexplorer.v20190423.models.ControlDeviceDataResponse;
import com.tencentcloudapi.iotexplorer.v20190423.models.DescribeDeviceDataResponse;
import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

@Slf4j
@RestController
@RequestMapping("openApi")
public class OpenController extends BaseController {

    @Autowired
    private ITencentService tencentService;
    @Autowired
    private IDeviceBindService deviceBindService;
    @Autowired
    private IDeviceService deviceService;

    @RequestMapping("unlock")
    public Result unlock(HttpServletRequest request, @RequestBody JSONObject params) throws TencentCloudSDKException, TerminalException, ForbiddenException, NoauthException {
        auth(request, params);
        String productId = params.getStr("productId");
        Assert.hasText(productId, "productId is null");
        String deviceName = params.getStr("deviceName");
        Assert.hasText(productId, "deviceName is null");
        int ch = params.getInt("channel", 1);
        JSONObject inputParams = new JSONObject();
        inputParams.set("ch", ch);
        CallDeviceActionSyncResponse response = tencentService.deviceActionSync(productId, deviceName, "unlock", inputParams.toString());
        if ("success".equals(response.getStatus())) {
            JSONObject outObj = JSONUtil.parseObj(response.getOutputParams());
            if (0 == outObj.getInt("code"))
                return Result.ok();
            else
                throw new InternalException("操作失败");
        } else {
            throw new TerminalException("终端无响应");
        }
    }

    @RequestMapping("switch")
    public Result deviceSwitch(HttpServletRequest request, @RequestBody JSONObject params) throws TencentCloudSDKException, TerminalException, ForbiddenException, NoauthException {
        auth(request, params);
        String productId = params.getStr("productId");
        Assert.hasText(productId, "productId is null");
        String deviceName = params.getStr("deviceName");
        Assert.hasText(productId, "deviceName is null");
        String stateStr = params.getStr("state");
        Assert.hasText(stateStr, "state is null");
        JSONObject inputParams = new JSONObject();
        inputParams.set("ch", params.getInt("channel", 1));
        inputParams.set("state", params.getInt("state"));
        CallDeviceActionSyncResponse response = tencentService.deviceActionSync(productId, deviceName, "switch", inputParams.toString());
        if (ObjectUtil.isEmpty(response.getStatus()) || "success".equals(response.getStatus())) {
            return Result.ok();
        } else {
            throw new TerminalException("终端无响应");
        }
    }

    @PostMapping("action")
    public Result action(HttpServletRequest request, @RequestBody JSONObject payload) throws TencentCloudSDKException, TerminalException, ForbiddenException, NoauthException {
        auth(request, payload);
        String productId = payload.getStr("productId");
        Assert.hasText(productId, "productId is null");
        String deviceName = payload.getStr("deviceName");
        Assert.hasText(productId, "deviceName is null");
        String params = payload.getStr("input");
        Assert.hasText(productId, "input is null");
        CallDeviceActionSyncResponse response = tencentService.deviceActionSync(productId, deviceName, payload.getStr("action"), params);
        if (ObjectUtil.isEmpty(response.getStatus()) || "success".equals(response.getStatus()) || "succ".equals(response.getStatus())) {
            return Result.ok();
        } else {
            throw new TerminalException("终端无响应");
        }
    }

    @PostMapping("property")
    public Result property(HttpServletRequest request, @RequestBody JSONObject payload) throws ForbiddenException, NoauthException, TencentCloudSDKException {
        auth(request, payload);
        String productId = payload.getStr("productId");
        Assert.hasText(productId, "productId is null");
        String deviceName = payload.getStr("deviceName");
        Assert.hasText(productId, "deviceName is null");
        DescribeDeviceDataResponse response = tencentService.property(productId, deviceName);
        JSONObject property = new JSONObject();
        JSONObject body = JSONUtil.parseObj(response.getData());
        for (String key : body.keySet()) {
            if (key.startsWith("count_down")
                    || key.equals("sync_status"))
                continue;
            property.set(key, body.get(key));
        }
        return Result.data(property);
    }

    @PostMapping("control")
    public Result control(HttpServletRequest request, @RequestBody JSONObject payload) throws ForbiddenException, NoauthException, TencentCloudSDKException {
        auth(request, payload);
        String productId = payload.getStr("productId");
        Assert.hasText(productId, "productId is null");
        String deviceName = payload.getStr("deviceName");
        Assert.hasText(productId, "deviceName is null");
        String data = payload.getStr("data");
        ControlDeviceDataResponse response = tencentService.controlDevice(productId, deviceName, data);
        return Result.data(response.getResult());
    }

    @PostMapping("deviceList")
    public Result deviceList(HttpServletRequest request, @RequestBody JSONObject payload) throws ForbiddenException, NoauthException, TencentCloudSDKException {
        auth(request, payload);
        String appKey = payload.getStr("appKey");
        List<Device> devs = deviceService.selectByAppKey(appKey);
        List<ThirdPartyDevice> data = new ArrayList<>();
        for (Device dev : devs) {
            ThirdPartyDevice item = new ThirdPartyDevice();
            item.setDeviceId(dev.getDeviceId());
            item.setAliasName(dev.getAliasName());
            item.setIccid(dev.getIccid());
            item.setLongitude(dev.getLongitude());
            item.setLatitude(dev.getLatitude());
            item.setDeviceStatus(dev.getDeviceStatus());
            JSONObject reported = dev.getReported();
            if (ObjectUtil.isNotNull(reported) && reported.containsKey("switch_1")) {
                item.setSwitchStatus(reported.getInt("switch_1"));
            }
            data.add(item);
        }
        return Result.data(data);
    }

    @PostMapping("deviceInfo")
    public Result deviceInfo(HttpServletRequest request, @RequestBody JSONObject payload) throws ForbiddenException, NoauthException, TencentCloudSDKException {
        auth(request, payload);
        String productId = payload.getStr("productId");
        Assert.hasText(productId, "productId is null");
        String deviceName = payload.getStr("deviceName");
        Assert.hasText(productId, "deviceName is null");
        DescribeDeviceResponse info = tencentService.describeDevice(productId, deviceName);
        JSONObject body = JSONUtil.createObj()
                .set("productId", productId)
                .set("deviceName", deviceName)
                .set("status", Long.valueOf(1L).equals(info.getOnline()) ? 1 : 0)
                .set("lastOfflineTime", info.getLastOfflineTime())
                .set("version", info.getVersion());
        return Result.data(body);
    }

    @GetMapping("userDevice")
    public Result userDevice(@RequestParam String unionId, @RequestParam String productId) {
        List<JSONObject> list = new ArrayList<>();
        List<Device> devs = deviceBindService.selectProductDeviceByUnionId(unionId, productId);
        if (ObjectUtil.isNotEmpty(devs)) {
            for (Device dev : devs) {
                list.add(JSONUtil.createObj().set("label", dev.getAliasName()).set("value", dev.getDeviceId()));
            }
        }
        return Result.data(list);
    }

    @PostMapping("exFactory")
    public Result exFactory(@RequestBody LabelPrintParams params) throws TencentCloudSDKException {
        int count = deviceService.exFactory(params);
        return Result.data(count);
    }

    @PostMapping("push")
    public void push(@RequestBody JSONObject obj) throws TencentCloudSDKException {
//        log.info(obj.toStringPretty());
    }

    @RequestMapping
    public JSONObject test(HttpServletRequest request) throws IOException {
        JSONObject result = new JSONObject();
        result.set("method", request.getMethod());
        log.info("请求方式 {}", request.getMethod());
        Enumeration<String> headers = request.getHeaderNames();
        log.info("====================header begin====================");
        JSONObject header = new JSONObject();
        while (headers.hasMoreElements()) {
            String key = headers.nextElement();
            String value = request.getHeader(key);
            header.set(key, value);
            log.info(String.format("%s: %s", key, value));
        }
        result.set("header", header);
        log.info("====================header end====================");
        Enumeration<String> fields = request.getParameterNames();
        JSONObject query = new JSONObject();
        log.info("====================parameter begin====================");
        while (fields.hasMoreElements()) {
            String key = fields.nextElement();
            String value = request.getParameter(key);
            query.set(key, value);
            log.info(String.format("%s: %s", key, value));
        }
        result.set("query", query);
        log.info("====================parameter end====================");
        log.info("====================body begin====================");
        StringBuilder body = new StringBuilder();
        String line;
        BufferedReader reader = request.getReader();
        try {
            while ((line = reader.readLine()) != null) {
                body.append(line);
            }
            result.set("body", body);
            log.info(body.toString());
        } finally {
            reader.close();
        }
        log.info("====================body end====================");
        return result;
    }

    @GetMapping("localProperty")
    public JSONObject localProperty(@RequestParam String productId, @RequestParam String deviceName) {
        Assert.hasText(productId, "productId is null");
        Assert.hasText(deviceName, "deviceName is null");
        return deviceService.localProperty(productId, deviceName);
    }
}
